package gsw.tool.pluggable.am;

import android.content.Context;
import android.content.pm.ActivityInfo;

import java.util.List;

/**
 * 自定义的AMS,用来管理宿主中的代理进程和组件，给插件组件分配合适的代理组件。
 */
public class ActivityManageService {
    //PMS服务的上下文
    private Context context;
    //静态代理进程列表：清单文件中注册的代理进程列表
    private StaticProcessList mStaticProcessList = new StaticProcessList();
    //正在运行的代理进程列表
    private RunningProcessList mRunningProcessList = new RunningProcessList();

    public ActivityManageService(Context context) {
        this.context = context;
        //初始化mStaticProcessList
        mStaticProcessList.onCreate(context);
    }

    /**
     * 选择代理Activity的存档信息
     * 根据插件的组件信息和进程ID、用户ID来选择可用的代理Activity的存档信息。
     * 因为单例Activity的代理Activity如果被启动了，就不能再启动，否则会注销之前启动的插件Activity。
     * 选择代理Activity时，需要遵循三个条件：
     * 1.统一插件的Activity运行在同一进程
     * 2.单例的Activity不能选择正在运行的代理Activity
     * 3.代理Activity的启动模式要与插件Activity的启动模式一样
     *
     * @param callingPid 进程ID
     * @param callingUid 用户ID
     * @param targetInfo 插件的Activity存档信息
     * @return 代理Activity的存档信息
     */
    public ActivityInfo selectStubActivityInfo(int callingPid, int callingUid, ActivityInfo targetInfo) {
        //获取插件Activity的同包Activity的运行进程，如果获取到了，就代表当前插件已经开启进程了
        String stubPlugin = mRunningProcessList.getStubProcessByTarget(targetInfo);
        //如果当前插件已经开启进程了，就选择可用的代理Activity
        if (stubPlugin != null) {
            //获取插件进程在清单文件中注册的所有代理Activity
            List<ActivityInfo> stunInfos = mStaticProcessList.getActivityInfoForProcessName(stubPlugin);
            for (ActivityInfo activityInfo : stunInfos) {
                //先找出与插件Activity的启动模式一致的代理Activity
                if (activityInfo.launchMode == targetInfo.launchMode) {
                    //如果启动模式是Standard，就直接返回该代理Activity
                    if (activityInfo.launchMode == ActivityInfo.LAUNCH_MULTIPLE) {
                        mRunningProcessList.setTargetProcessName(activityInfo, targetInfo);
                        mRunningProcessList.addActivityInfo(callingPid, callingUid, activityInfo, targetInfo);
                        return activityInfo;
                        //如果启动模式是单例，就返回没有运行的代理Activity
                    } else if (!mRunningProcessList.isStubInfoUsed(activityInfo, targetInfo, stubPlugin)) {
                        mRunningProcessList.setTargetProcessName(activityInfo, targetInfo);
                        mRunningProcessList.addActivityInfo(callingPid, callingUid, activityInfo, targetInfo);
                        return activityInfo;
                    }
                }
            }
            return null;
        }

        /**
         * 如果当前插件没有开启进程，就需要新开进程
         */
        //获取清单文件中注册的所有代理进程名
        List<String> processNames = mStaticProcessList.getProcessNames();
        for (String stubProcessName : processNames) {
            //获取插件进程在清单文件中注册的所有代理Activity
            List<ActivityInfo> stubInfos = mStaticProcessList.getActivityInfoForProcessName(stubProcessName);
            //如果当前进程没有运行，就设置它的目标进程名和包名，并查找可用的代理ActivityInfo
            if (!mRunningProcessList.isProcessRunning(stubProcessName)) {
                for (ActivityInfo stubInfo : stubInfos) {
                    if (stubInfo.launchMode == targetInfo.launchMode) {
                        if (stubInfo.launchMode == ActivityInfo.LAUNCH_MULTIPLE) {
                            mRunningProcessList.setTargetProcessName(stubInfo, targetInfo);
                            mRunningProcessList.addActivityInfo(callingPid, callingUid, stubInfo, targetInfo);
                            return stubInfo;
                        } else if (!mRunningProcessList.isStubInfoUsed(stubInfo, targetInfo, stubProcessName)) {
                            mRunningProcessList.setTargetProcessName(stubInfo, targetInfo);
                            mRunningProcessList.addActivityInfo(callingPid, callingUid, stubInfo, targetInfo);
                            return stubInfo;
                        }
                    }
                }
                //如果当前进程已经运行，但是并没有代理运行任何插件，就重新设置它的目标进程名和包名，并查找可用的代理ActivityInfo
            } else if (mRunningProcessList.isProcessRunning(stubProcessName) && mRunningProcessList.isPkgEmpty(stubProcessName)) {
                for (ActivityInfo stubInfo : stubInfos) {
                    if (stubInfo.launchMode == targetInfo.launchMode) {
                        if (stubInfo.launchMode == ActivityInfo.LAUNCH_MULTIPLE) {
                            mRunningProcessList.setTargetProcessName(stubInfo, targetInfo);
                            mRunningProcessList.addActivityInfo(callingPid, callingUid, stubInfo, targetInfo);
                            return stubInfo;
                        } else if (!mRunningProcessList.isStubInfoUsed(stubInfo, targetInfo, stubProcessName)) {
                            mRunningProcessList.setTargetProcessName(stubInfo, targetInfo);
                            mRunningProcessList.addActivityInfo(callingPid, callingUid, stubInfo, targetInfo);
                            return stubInfo;
                        }
                    }
                }
            }
        }
        return null;
    }

    /**
     * 开启代理组件的进程时，初始自定义AMS中的代理进程的信息
     *
     * @param callingPid        进程ID
     * @param callingUid        用户ID
     * @param stubProcessName   代理进程名
     * @param targetProcessName 目标进程名
     * @param targetPkg         目标包名
     */
    public void onOpenPluginProcess(int callingPid, int callingUid, String stubProcessName, String targetProcessName, String targetPkg) {
        mRunningProcessList.addItem(callingPid, callingUid);
        mRunningProcessList.setProcessName(callingPid, stubProcessName, targetProcessName, targetPkg);
    }
}
